namespace mecs {

    /** 继承sys类时,记得一定要在其中声明: static NAME = 'XXXSystem' 默认使用 static NAME 防止重名system类 */
    export abstract class BaseSys implements IDataNode {

        /** 当前sys关注的实体 */
        entities: HashList<BaseEntity>;
        /** 当前sys所在的world */
        world: BaseWorld;
        protected _compTupleNames: string[]
        /** 每次处理的间隔，单位：帧 */
        protected mInterval: number;
        /** 上次处理的帧 */
        protected mLastExeFrame: number;
        /** 和上次处理的帧间隔 */
        protected mDeltaLastFrame: number;
        /** 上次处理时的时间 */
        protected mLastTimestamp: number;
        /** 和上次处理时间的间隔 */
        protected mDeltaTimestamp: number;

        constructor(world: BaseWorld) {
            this.world = world;
            this.mInit()
        }

        protected mInit() {
            this.entities = new HashList([], 'sid');
            this.mLastExeFrame = 0;
            this.mInterval = 1;
            this.mDeltaTimestamp = 0
            this.mLastTimestamp = this.world.logicTime;
        }

        /** 此系统关注的组件元组，用以在增加元组时判断用 */
        abstract get compTuples(): typeof BaseComp[];

        get compTupleNames() {
            if (!this._compTupleNames) {
                this._compTupleNames = this.compTuples.map(c => c['NAME']);
            }
            return this._compTupleNames
        }

        get sysName() {
            return this["constructor"]["NAME"];
        }

        /** 增加此system关注的实体 */
        addEntity(entity: BaseEntity) {
            if (EntityUtil.hasCompByCls(entity, this.compTuples)) {
                if(this.entities.addData(entity.sid, entity)){
                    this.mOnAddEntity(entity);
                }
            }
        }

        /** 具体获得某个system关注的实体 */
        getEntity(sid: number) {
            return this.entities.getData(sid);
        }

        /** 删除此system关注的实体 */
        removeEntity(entity: BaseEntity | number) {
            if (!this.entities) return;
            if (typeof entity != 'number') {
                entity = entity.sid;
            }
            entity=this.entities.removeData(entity);
            entity && this.mOnRemoveEntity(entity);
        }

        dispose() {
            if(this.entities){
                this.entities.dispose()
            }
            this.entities = null;
            this._compTupleNames = null;
            this.world = null;
        }

        /** 这里传入的time是当前的world的时间，world的时间是从0开始的 */
        update(time: number) {
            this.mDeltaLastFrame = this.world.logicFrame.crtId - this.mLastExeFrame;
            if (this.mDeltaLastFrame < this.mInterval) {
                // 如果当前帧-上次运行时帧 < 间隔帧数，则不运行当前逻辑
                return;
            }
            this.mDeltaTimestamp = time - this.mLastTimestamp;
            this.mUpdate(time);
            this.mLastExeFrame = this.world.logicFrame.crtId;
            this.mLastTimestamp = time;
        }

        resetData(data: ICacheSys) {
            this.mLastExeFrame = data.mLastTime;
            this.mDeltaTimestamp = data.mDeltaTimestamp;
            this.mLastTimestamp = data.mLastTimestamp;
        }

        cloneData() {
            let d: ICacheSys = {
                sysName: this.sysName,
                mLastTime: this.mLastExeFrame,
                mDeltaTimestamp: this.mDeltaTimestamp,
                mLastTimestamp: this.mLastTimestamp
            };
            return d;
        }

        protected mUpdate(time: number) {
            if (!this.entities) return;
            this.entities.forEach((e) => {
                if (!e) return;
                // 过滤出符合要求的实体，运行逻辑
                if (this.mFilter(e)) {
                    this.mUpdateEntity(e, time);
                }
            })
            /* let arr = this.entities.arr;
            let len = this.entities.length;
            for (let i = 0; i < len; i++) {
                let e = arr[i];
                if (!e) continue;

                // 过滤出符合要求的实体，运行逻辑
                if (this.mFilter(e)) {
                    this.mUpdateEntity(e, time);
                }
            } */
        }

        protected mFilter(entity: mecs.BaseEntity): boolean {
            return true;
        }

        /**当sys增加entity时调用，可重写 */
        protected mOnAddEntity(entity: mecs.BaseEntity) { }
        /**当sys移除entity时调用，可重写 */
        protected mOnRemoveEntity(entity: mecs.BaseEntity) { }

        protected abstract mUpdateEntity(entity: mecs.BaseEntity, time: number);
    }
}